#include <gtest/gtest.h>
#include "ringbuffer.h"

class TestRingBuffer : public testing::Test
{
protected:
    static void SetUpTestSuite()
    {
    }
    static void TearDownTestSuite()
    {
    }
    virtual void SetUp() override
    {
    }
    virtual void TearDown() override
    {
    }
};

TEST_F(TestRingBuffer, ring_buffer_base)
{
    RingBuffer buffer;
    buffer_err ret = RingBuffer_Ctor(&buffer);
    ASSERT_EQ(RING_BUFFER_OK, ret);

    buf_size_t free_size = buffer.get_total_count(&buffer);
    ASSERT_EQ(0, free_size);
}

TEST_F(TestRingBuffer, ring_buffer_static_buffer)
{
    RingBuffer buffer;
    uint8_t buf[128];
    buffer_err ret = RingBuffer_Ctor(&buffer);
    ASSERT_EQ(RING_BUFFER_OK, ret);
    RingBufferSection static_buffer = {buf, sizeof(buf)};
    ret = buffer.extent_static_buffer(&buffer, &static_buffer);
    ASSERT_EQ(RING_BUFFER_OK, ret);
    buf_size_t free_size = buffer.get_total_count(&buffer);
    EXPECT_EQ(sizeof(buf), free_size);
}

TEST_F(TestRingBuffer, ring_buffer_extend_buffer)
{
    RingBuffer buffer;
    uint8_t buf[128];

    buffer_err ret = RingBuffer_Ctor(&buffer);
    ASSERT_EQ(RING_BUFFER_OK, ret);
    RingBufferSection static_buffer = {buf, sizeof(buf)};
    ret = buffer.extent_static_buffer(&buffer, &static_buffer);
    ASSERT_EQ(RING_BUFFER_OK, ret);
    ret = buffer.extend_dynamic_buffer(&buffer, 100);
    ASSERT_EQ(RING_BUFFER_OK, ret);

    buf_size_t free_size = buffer.get_total_count(&buffer);
    EXPECT_EQ(sizeof(buf) + 100, free_size);
}

TEST_F(TestRingBuffer, ring_buffer_write)
{
    RingBuffer buffer;
    uint8_t buf[10];

    buffer_err ret = RingBuffer_Ctor(&buffer);
    ASSERT_EQ(RING_BUFFER_OK, ret);
    RingBufferSection static_buffer = {buf, sizeof(buf)};
    ret = buffer.extent_static_buffer(&buffer, &static_buffer);
    ASSERT_EQ(RING_BUFFER_OK, ret);
    ret = buffer.extend_dynamic_buffer(&buffer, 20);
    ASSERT_EQ(RING_BUFFER_OK, ret);

    uint8_t write_content[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29};
    ret = buffer.write(&buffer, write_content, sizeof(write_content));
    ASSERT_EQ(RING_BUFFER_OK, ret);
    int cmp_ret = memcmp(buf, write_content, 10);
    EXPECT_EQ(0, cmp_ret);

    uint8_t *dyn_buf = buffer.buffer_list->next->buf;
    cmp_ret = memcmp(dyn_buf, &write_content[10], 10);
    EXPECT_EQ(0, cmp_ret);
}

TEST_F(TestRingBuffer, ring_buffer_multi_write)
{
    RingBuffer buffer;
    uint8_t buf[10];
    uint8_t expect_content1[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    uint8_t expect_content2[] = {20, 21, 22, 23, 24, 25, 26, 27, 28, 29};

    buffer_err ret = RingBuffer_Ctor(&buffer);
    ASSERT_EQ(RING_BUFFER_OK, ret);
    RingBufferSection static_buffer = {buf, sizeof(buf)};
    ret = buffer.extent_static_buffer(&buffer, &static_buffer);
    ASSERT_EQ(RING_BUFFER_OK, ret);
    ret = buffer.extend_dynamic_buffer(&buffer, 10);
    ASSERT_EQ(RING_BUFFER_OK, ret);

    uint8_t write_content1[] = {0, 1, 2, 3, 4, 5};
    ret = buffer.write(&buffer, write_content1, sizeof(write_content1));
    ASSERT_EQ(RING_BUFFER_OK, ret);
    uint8_t write_content2[] = {6, 7, 8, 9, 20, 21, 22};
    ret = buffer.write(&buffer, write_content2, sizeof(write_content2));
    ASSERT_EQ(RING_BUFFER_OK, ret);
    uint8_t write_content3[] = {23, 24, 25, 26, 27, 28, 29};
    ret = buffer.write(&buffer, write_content3, sizeof(write_content3));
    ASSERT_EQ(RING_BUFFER_OK, ret);
    int cmp_ret = memcmp(buf, expect_content1, 10);
    EXPECT_EQ(0, cmp_ret);
    uint8_t *dyn_buf = buffer.buffer_list->next->buf;
    cmp_ret = memcmp(dyn_buf, expect_content2, 10);
    EXPECT_EQ(0, cmp_ret);

    buf_size_t free_cnt = buffer.get_free_count(&buffer);
    ASSERT_EQ(0, free_cnt);
    ret = buffer.write(&buffer, write_content3, 1);
    ASSERT_EQ(RING_BUFFER_FAIL, ret);
}

// read
// how to read
// buffer used count decrease after read.
TEST_F(TestRingBuffer, ring_buffer_read_no_extend)
{
    RingBuffer buffer;
    uint8_t buf[10];

    buffer_err ret = RingBuffer_Ctor(&buffer);
    ASSERT_EQ(RING_BUFFER_OK, ret);
    RingBufferSection static_buffer = {buf, sizeof(buf)};
    ret = buffer.extent_static_buffer(&buffer, &static_buffer);
    ASSERT_EQ(RING_BUFFER_OK, ret);

    uint8_t write_content[] = {5, 4, 3, 2, 1, 6, 8, 9, 10};
    ret = buffer.write(&buffer, write_content, sizeof(write_content));
    ASSERT_EQ(RING_BUFFER_OK, ret);

    uint8_t read_buf[10];
    buf_size_t read_size;
    read_size = buffer.read(&buffer, read_buf, 2);
    EXPECT_EQ(2, read_size);
    int cmp_ret = memcmp(read_buf, write_content, 2);
    EXPECT_EQ(0, cmp_ret);
    read_size = buffer.read(&buffer, read_buf, 2);
    EXPECT_EQ(2, read_size);
    cmp_ret = memcmp(read_buf, &write_content[2], 2);
    EXPECT_EQ(0, cmp_ret);
    read_size = buffer.read(&buffer, read_buf, 5);
    EXPECT_EQ(5, read_size);
    cmp_ret = memcmp(read_buf, &write_content[4], 5);
    EXPECT_EQ(0, cmp_ret);
    read_size = buffer.read(&buffer, read_buf, 5);
    EXPECT_EQ(0, read_size);
}

// 单buffer 循环写与循环读
TEST_F(TestRingBuffer, single_buffer_read_write_loop)
{
    RingBuffer buffer;
    uint8_t buf[10];

    buffer_err ret = RingBuffer_Ctor(&buffer);
    ASSERT_EQ(RING_BUFFER_OK, ret);
    RingBufferSection static_buffer = {buf, sizeof(buf)};
    ret = buffer.extent_static_buffer(&buffer, &static_buffer);
    ASSERT_EQ(RING_BUFFER_OK, ret);

    uint8_t write_content[] = {5, 4, 3, 2, 1, 0};
    ret = buffer.write(&buffer, write_content, sizeof(write_content));
    ASSERT_EQ(RING_BUFFER_OK, ret);

    uint8_t read_buf[10];
    buf_size_t read_size;
    read_size = buffer.read(&buffer, read_buf, 6);
    EXPECT_EQ(6, read_size);
    int cmp_ret = memcmp(read_buf, write_content, 6);
    EXPECT_EQ(0, cmp_ret);

    ret = buffer.write(&buffer, write_content, sizeof(write_content));
    ASSERT_EQ(RING_BUFFER_OK, ret);
    memset(read_buf, 0, 6);
    read_size = buffer.read(&buffer, read_buf, 6);
    EXPECT_EQ(6, read_size);
    cmp_ret = memcmp(read_buf, write_content, 6);
    EXPECT_EQ(0, cmp_ret);
    read_size = buffer.read(&buffer, read_buf, 5);
    EXPECT_EQ(0, read_size);

    ret = buffer.write(&buffer, write_content, sizeof(write_content));
    ASSERT_EQ(RING_BUFFER_OK, ret);
    memset(read_buf, 0, 6);
    read_size = buffer.read(&buffer, read_buf, 6);
    EXPECT_EQ(6, read_size);
    cmp_ret = memcmp(read_buf, write_content, 6);
    EXPECT_EQ(0, cmp_ret);
    read_size = buffer.read(&buffer, read_buf, 5);
    EXPECT_EQ(0, read_size);
}

// multi buffer read and write loop
TEST_F(TestRingBuffer, multi_buffer_read_write_loop)
{
    RingBuffer buffer;
    buffer_err ret = RingBuffer_Ctor(&buffer);
    ASSERT_EQ(RING_BUFFER_OK, ret);
    ret = buffer.extend_dynamic_buffer(&buffer, 10);
    ASSERT_EQ(RING_BUFFER_OK, ret);
    ret = buffer.extend_dynamic_buffer(&buffer, 10);
    ASSERT_EQ(RING_BUFFER_OK, ret);

    uint8_t write_content[] = {5, 4, 3, 2, 1};
    ret = buffer.write(&buffer, write_content, sizeof(write_content));
    ASSERT_EQ(RING_BUFFER_OK, ret);

    uint8_t read_buf[20];
    buf_size_t read_size;
    read_size = buffer.read(&buffer, read_buf, 6);
    EXPECT_EQ(5, read_size);
    int cmp_ret = memcmp(read_buf, write_content, 5);
    EXPECT_EQ(0, cmp_ret);

    uint8_t write_content2[] = {5, 4, 3, 2, 1, 1, 2, 3, 4, 5, 5, 4, 3, 2, 1};
    ret = buffer.write(&buffer, write_content2, sizeof(write_content2));
    ASSERT_EQ(RING_BUFFER_OK, ret);
    read_size = buffer.read(&buffer, read_buf, 15);
    EXPECT_EQ(15, read_size);
    cmp_ret = memcmp(read_buf, write_content2, 15);
    EXPECT_EQ(0, cmp_ret);

    memset(write_content2, 0, 15);
    ret = buffer.write(&buffer, write_content2, sizeof(write_content2));
    ASSERT_EQ(RING_BUFFER_OK, ret);
    read_size = buffer.read(&buffer, read_buf, 15);
    EXPECT_EQ(15, read_size);
    cmp_ret = memcmp(read_buf, write_content2, 15);
    EXPECT_EQ(0, cmp_ret);
}

// extend data security
TEST_F(TestRingBuffer, buffer_extend_security)
{
    RingBuffer buffer;
    buffer_err ret = RingBuffer_Ctor(&buffer);
    ASSERT_EQ(RING_BUFFER_OK, ret);
    ret = buffer.extend_dynamic_buffer(&buffer, 10);
    ASSERT_EQ(RING_BUFFER_OK, ret);

    uint8_t write_content[] = {5, 4, 3, 2, 1};
    ret = buffer.write(&buffer, write_content, sizeof(write_content));
    ASSERT_EQ(RING_BUFFER_OK, ret);
    uint8_t read_buf[20];
    buf_size_t read_size;
    read_size = buffer.read(&buffer, read_buf, 5);
    EXPECT_EQ(5, read_size);
    int cmp_ret = memcmp(read_buf, write_content, 5);
    EXPECT_EQ(0, cmp_ret);

    uint8_t write_content2[] = {5, 4, 3, 2, 1, 1, 2, 3, 4, 5};
    ret = buffer.write(&buffer, write_content2, sizeof(write_content2));
    ASSERT_EQ(RING_BUFFER_OK, ret);
    ret = buffer.extend_dynamic_buffer(&buffer, 10);
    ASSERT_EQ(RING_BUFFER_OK, ret);

    read_size = buffer.read(&buffer, read_buf, 10);
    EXPECT_EQ(10, read_size);
    cmp_ret = memcmp(read_buf, write_content2, 10);
    EXPECT_EQ(0, cmp_ret);

    read_size = buffer.read(&buffer, read_buf, 10);
    EXPECT_EQ(0, read_size);
}
